<?php

    /**
     * 意图：
     * 想实现一个配置，因为一般来说配置是需要mc之类的缓存的，不可能每次都读数据库吧
     * 调用DB或文件接口 应支持二级配置，如 $config->getConfig('base.imgFolder');
     *
     */

	include_once( PLOG_CLASS_PATH."class/config/properties.class.php" );
    include_once( PLOG_CLASS_PATH."class/config/configfilestorage.class.php" );
    include_once( PLOG_CLASS_PATH."class/config/configdbstorage.class.php" );

    /**
     * Set it to either "file" or "db"
     */
    define( DEFAULT_STORAGE_BACKEND, "db" );
    
    $ADODB_CACHE_DIR = "./tmp";

    /**
     * Extends the Properties class so that our own configuration file is automatically loaded.
     * The configuration file is under config/config.properties.php
     *
     * It is recommented to use this function as a singleton rather than as an object.
     * @see Config
     * @see getConfig
     */
	class Config extends Object {

    	// mappings to the storage classes
        // more can be added any time
    	var $_storage = Array(
        	"file" => "ConfigFileStorage",
            "db"   => "ConfigDbStorage"
        );

        var $_storageType;
        var $_storageClassName;
        var $_storageObject;

    	/**
         * Initializes the configuration back end.
         *
         * Unless strictly necessary, it is recommended to use the getConfig function,
         * built around the idea of the Singleton pattern.
         * It will also bring increased performance since then there is no need to create the
         * whole ConfigXxxxStorage object. For instance, in the case of the ConfigDbStorage,
         * the whole config table is retrieved in the constructor... Using a singleton will
         * save us that work.
         * @param storage One of the storage methods implemented. Available ones are
         * "db" and "file", but any other can be implemented.
         * @param params An array containing storage backend specific parameters. In the case
         * of the file-based storage it could be the name of the file to use (for example)
         */
		function Config( $storage = DEFAULT_STORAGE_BACKEND, $params = null )
		{
			$this->Object();

            // now we have to instantiate the right storage class
            $this->_storageType = $storage;
            if( $storage == "" || !array_key_exists( $this->_storageType, $this->_storage )) {
            	// there is no class to implement this storage method, so we quite
                // because this is quite a severe error
            	throw(new Exception( "Config class Exception: no storage class found for storage parameter = ".$storage ));
                die();
            }

            // if all went fine, get the name for that class
            $className = $this->_storage[$this->_storageType];
            $this->_storageClassName = $className;
            // and create an object
            $this->_storageObject = new $className( $params );
		}

        /**
         * Makes sure that there is <b>only one</b> instance of this class for everybody.
         * It is not bad to call the constructor but using the getConfig we will
         * save some work.
         *
         * @param storage One of the storage methods implemented. Available ones are
         * "db" and "file", but any other can be implemented.
         * @param params An array containing storage backend specific parameters. In the case
         * of the file-based storage it could be the name of the file to use (for example)
         * @return Returns an instance of the Config class, be it a new one if this is the first
         * time we were calling it or an already created one if somebody else called
         * this method before.
         * @see ConfigDbStorage
         * @see ConfigFileStorage
         */
        function &getConfig( $storage = DEFAULT_STORAGE_BACKEND, $params = null )
        {
        	static $configInstance;

            // check if there was an instance of the Config class already created
            if( !isset($configInstance)) {
            	// if there wasn't, then create a new one
            	$configInstance = new Config( $storage, $params );
            }

            // return the instance
            return $configInstance;
        }

        /**
         * Returns a string representing the storage backend that we are using
         * to store the settings.
         *
         * @return At the moment it's either "db" or "file", depending on our configuration
         */
        function getStorageMethod()
        {
        	return $this->_storageType;
        }

        /**
         * Returns the value assigned to a given key in the config storage.
         *
         * @param key The name of the key we're looking for
         * @param defaultValue If the key does not exist, we can assign a default
         * value to it. Optional.
         * @return Returns the value assigned to the key in the config storage or
         * the $defaultValue parameter if specified and the key was not found.
         */
        function getValue( $key, $defaultValue = null )
        {
        	return $this->_storageObject->getValue( $key, $defaultValue );
        }

        /**
         * Sets a value in the storage backend.
         *
         * @param key The name of the key to which we are going to assign the value.
         * @param value The value that will be assigned to the key.
         * @return True if the value was set successfully or false otherwise.
         */
        function setValue( $key, $value )
        {
        	return $this->_storageObject->setValue( $key, $value );
        }


        /**
         * Reloads the contents from the configuration file.
         *
         * @return Returns always true.
         */
        function reload()
        {
        	return $this->_storageObject->reload();
        }

        /**
         * Returns the name of the configuration file being used.
         *
         * @return The name of the configuration file being used.
         */
        function getConfigFileName()
        {
        	return $this->_storageObject->getConfigFileName();
        }

        /**
         * Saves just one setting to the configuration storage. If the setting already exists, the current
         * value is overwritten. Otherwise, it will be added as new.
         *
         * @param name Name of the setting.
         * @param value Value of the setting.
         * @return True if success or false otherwise.
         */
        function saveValue( $name, $value )
        {
        	return $this->_storageObject->saveValue( $name, $value );
        }

        /**
         * Tells the configuration backend to put <b>ALL</b> the values back in the storage, so that
         * they become permanent.
         *
         * @return Returns always true.
         */
        function save()
        {
        	return $this->_storageObject->save();
        }

        /**
         * Return an array with all the keys available.
         *
         * @return An associative array with all the keys available, or an empty array
         * if there are no keys
         */
        function getKeys()
        {
        	return $this->_storageObject->getKeys();
        }

        /**
         * Return an array with all the values available.
         *
         * @return An associative array with all the values available, or an empty array
         * if there are no values.
         */
        function getValues()
        {
        	return $this->_storageObject->getValues();
        }

        /**
         * Returns an array of pairs (key,value), if needed.
         *
         * @return An array of pairs (key,value). If there are no values, the array
         * will be empty.
         */
        function getAsArray()
        {
        	return $this->_storageObject->getAsArray();
        }
	}
?>
